package org.jeecg.modules.couteachingjobexecute.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.config.mybatis.TenantContext;
import org.jeecg.modules.classes.entity.CouClass;
import org.jeecg.modules.classes.service.impl.CouClassServiceImpl;
import org.jeecg.modules.common.api.IRow2ColTransfer;
import org.jeecg.modules.common.baseentity.BaseApiEntity;
import org.jeecg.modules.common.baseentity.Row2ColModel;
import org.jeecg.modules.common.utils.DateUtil;
import org.jeecg.modules.commonmode.reldateweek.entity.RelDateWeek;
import org.jeecg.modules.commonmode.reldateweek.service.IRelDateWeekService;
import org.jeecg.modules.commonmode.reldateweek.service.impl.RelDateWeekServiceImpl;
import org.jeecg.modules.coucoursearrange.entity.CouCourseArrange;
import org.jeecg.modules.coucoursearrange.service.impl.CouCourseArrangeServiceImpl;
import org.jeecg.modules.coursearrangeatom.entity.CouCourseArrangeAtom;
import org.jeecg.modules.coursearrangeatom.service.impl.CouCourseArrangeAtomServiceImpl;
import org.jeecg.modules.courseplan.entity.CouCoursePlan;
import org.jeecg.modules.courseplan.service.impl.CouCoursePlanServiceImpl;
import org.jeecg.modules.couteachingjobexecute.entity.CouTeachingJobExecute;
import org.jeecg.modules.couteachingjobexecute.mapper.CouTeachingJobExecuteMapper;
import org.jeecg.modules.couteachingjobexecute.service.ICouTeachingJobExecuteService;
import org.jeecg.modules.couteachingjobexecute.vo.CouTeachingJobExecuteVo;
import org.jeecg.modules.grade.entity.CouGrade;
import org.jeecg.modules.grade.service.impl.CouGradeServiceImpl;
import org.jeecg.modules.relation.relcourseplanapp.service.impl.RelCoursePlanAppServiceImpl;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

//import javax.transaction.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * @Description: cou_teaching_job_execute
 * @author: baochangrong
 * @Date: 2022-04-11
 * @Version: V1.0
 */
@Service
public class CouTeachingJobExecuteServiceImpl extends ServiceImpl<CouTeachingJobExecuteMapper, CouTeachingJobExecute> implements ICouTeachingJobExecuteService {
    @Autowired
    private CouTeachingJobExecuteMapper couTeachingJobExecuteMapperImpl;
    @Autowired
    private CouCoursePlanServiceImpl couCoursePlanService;
    @Autowired
    private RelCoursePlanAppServiceImpl relCoursePlanAppService;
    @Autowired
    private CouCourseArrangeAtomServiceImpl couCourseArrangeAtomService;
    @Autowired
    private CouClassServiceImpl couClassService;
    @Autowired
    private CouGradeServiceImpl couGradeService;
    @Autowired
    private CouCourseArrangeServiceImpl couCourseArrangeService;
    @Autowired
    private ISysBaseAPI sysBaseAPI;
    @Autowired
    private IRow2ColTransfer row2ColTransfer;
    @Autowired
    private RelDateWeekServiceImpl relDateWeekServiceImpl;

    @Override
    @Transactional
    public Result runTeachingJobExecute(CouTeachingJobExecuteVo couTeachingJobExecuteVo, BaseApiEntity baseApiEntity) {

        /**
         * #{execId}, 主鍵
         * #{teachingJobExeStatus}, 科目默认状态默认为正常上课状态（1正常，21代出课 22代入课(insert)，31交换出 32交换入）
         * #{izOpen}, 是否启用数据
         * #{sysOrgCode}, 部门编码
         * #{courseArrangeId}, 课表模板ID
         * #{targetObjId}, 班级ID
         * #{tenantId}, 学校ID
         * #{minTime}, 计划开始时间
         * #{maxTime}  计划结束时间  return Result.OK("选择的不是发布动作所以不需要执行生成执行计划！");
         *
         */
        //发布动作才进入到这里
        if ("4".equals(couTeachingJobExecuteVo.getArrangeStatus())) {
            Map mapInfo = new HashMap();
            Map whereInfo = new HashMap();
            //根据课表ID查询，学年学期，年级信息,查询状态为3的已排课的数据
            whereInfo.put("ids", couTeachingJobExecuteVo.getCourseArrangeIdArray());
            List<CouCourseArrange> couCourseArrangeList = couCourseArrangeService.queryArrangeYearSemesterGradeIds(whereInfo);
            if (couCourseArrangeList.size() < 1) {

                new IllegalArgumentException("根据课表ID,没有查询到已排课的课表，请检查数据！");
                return Result.error("根据课表ID,没有查询到已排课的课表，请检查数据！");
            }
            QueryWrapper<RelDateWeek> queryWrapperRelDateWeek = new QueryWrapper<>();
            queryWrapperRelDateWeek.eq("date_format(date_time,'%Y')", DateUtil.getNow("yyyy"));
            List<RelDateWeek> relDateWeekList = relDateWeekServiceImpl.list(queryWrapperRelDateWeek);
            if(null == relDateWeekList || relDateWeekList.size() < 1){
                Result result = relDateWeekServiceImpl.saveRelDateWeek(DateUtil.getNow("yyyy"));
                if(!result.isSuccess()){
                    new IllegalArgumentException("生成本年度节假日信息错误，请联系管理员！");
                    return Result.error("生成本年度节假日信息错误，请联系管理员！");
                }
            }
            for (CouCourseArrange couCourseA : couCourseArrangeList) {
                /**
                 *
                 * mybatis 拦截器会对设置了租户表的操作，检测是否带有tenantId ,没有传入会默认设置为1
                 * 所以如果要分租户查询就使用 TenantContext.setTenant("128"); Tenant上下文对象，设置租户值。详细代码见
                 * core 包的 MybatisPlusSaasConfig
                 */
                QueryWrapper CouCoursePlanQueryWrapper = new QueryWrapper<CouCoursePlan>();
                CouCoursePlanQueryWrapper.eq("school_year_id", couCourseA.getSchoolYearId());
                CouCoursePlanQueryWrapper.eq("semester_id", couCourseA.getSemesterId());
                CouCoursePlanQueryWrapper.eq("grade_id", couCourseA.getGradeCode());
                CouCoursePlanQueryWrapper.eq("tenant_id", couCourseA.getTenantId());
                CouCoursePlan couCoursePlansOne = couCoursePlanService.getOne(CouCoursePlanQueryWrapper);
                if (couCoursePlansOne == null) {
                    new IllegalArgumentException("根据学期学年以及年级数据没有查询到教学计划，请检查数据！");
                    return Result.error("根据学期学年以及年级数据没有查询到教学计划，请检查数据！");
                }

                String targetObjId = couCourseA.getTargetObjId();
                String courseArrangeId = couCourseA.getId();
                QueryWrapper queryWrapper = new QueryWrapper<CouCourseArrangeAtom>();
                queryWrapper.eq("target_obj_id", targetObjId);
                queryWrapper.eq("course_arrange_id", courseArrangeId);
                queryWrapper.eq("tenant_id", couCourseA.getTenantId());
                long couCourseArrangeAtomsCont = couCourseArrangeAtomService.count(queryWrapper);
                if (couCourseArrangeAtomsCont < 1) {
                    new IllegalArgumentException("根据课表模板ID,班级ID 没有查询到课表明细，请检查数据！");
                    return Result.error("根据课表模板ID,班级ID 没有查询到课表明细，请检查数据！是否发布了模板");
                }


                //组装查询条件
                mapInfo.put("startTime", couCoursePlansOne.getCoursePlanStartDate()); //教学计划开始时间
                mapInfo.put("minTime", couCourseA.getOpenStartTime()); //课表明细启用时间
                mapInfo.put("maxTime", couCourseA.getOpenStopTime()); //课表明细结束时间
                mapInfo.put("courseArrangeId", courseArrangeId);
                mapInfo.put("targetObjId", targetObjId);
                mapInfo.put("tenantId", couCourseA.getTenantId());
                //默认值
                mapInfo.put("teachingJobExeStatus", "1");
                mapInfo.put("izOpen", "1");
                mapInfo.put("sysOrgCode", baseApiEntity.getSysOrgCode());
                mapInfo.put("createBy", baseApiEntity.getCreateBy());
                mapInfo.put("createTime", DateUtil.getNow(DateUtil.DATE_FORMATE_STRING_A));
                //验证map转对象
                //先清理当前计划下，当前班级，当前租户，当前角色下的数据
                Map delMap = new HashMap();
                delMap.put("courseArrangeId", courseArrangeId); //课表ID
                delMap.put("minTime", couCourseA.getOpenStartTime()); //课表明细启用时间
                delMap.put("maxTime", couCourseA.getOpenStopTime()); //课表明细结束时间
                delMap.put("targetObjId", targetObjId); //班级ID
                delMap.put("tenantId", baseApiEntity.getTenantId());
                delMap.put("sysOrgCode", baseApiEntity.getSysOrgCode());
                couTeachingJobExecuteMapperImpl.delTeachingJobExecute(delMap);
                //修改表id为自增，采用直接insert into select 方式处理写入
                int flage = couTeachingJobExecuteMapperImpl.runTeachingJobExecuteDataAll(mapInfo);
                if (flage < 1) {
                    new IllegalArgumentException("根据教学计划生成执行计划失败！");
                    return Result.error("根据教学计划生成执行计划失败！");
                }
                CouCourseArrange updateCouCourseArrange = new CouCourseArrange();
                updateCouCourseArrange.setId(couCourseA.getId());
                updateCouCourseArrange.setCourseArrangeStatus(couTeachingJobExecuteVo.getArrangeStatus());
                if (!couCourseArrangeService.updateById(updateCouCourseArrange)) {
                    new IllegalArgumentException("修改课表状态失败！");
                    return Result.error("修改课表状态失败！");
                }

            }
            return Result.OK("教学任务日期生成成功！");
            //撤回重排的时候 需要将3，6 状态的已排课，已撤回重排的数据进行下线，并修改执行计划表数据为失效
        } else if ("5".equals(couTeachingJobExecuteVo.getArrangeStatus())) {
            Map mapInfo = new HashMap();
            Map whereInfo = new HashMap();
            //根据课表ID查询，学年学期，年级信息,查询状态为3，6的已排课重排课的课表数据
            whereInfo.put("ids", couTeachingJobExecuteVo.getCourseArrangeIdArray());
            List<CouCourseArrange> couCourseArrangeList = couCourseArrangeService.queryArrangeYearSemesterGradeIds(whereInfo);
            if (couCourseArrangeList.size() < 1) {

                new IllegalArgumentException("根据课表ID,没有查询到已排课的课表，请检查数据！");
                return Result.error("根据课表ID,没有查询到已排课的课表，请检查数据！");
            }
            for (CouCourseArrange couCourseA : couCourseArrangeList) {
                //验证map转对象
                //先清理当前计划下，当前班级，当前租户，当前角色下的数据
                Map delMap = new HashMap();
                delMap.put("courseArrangeId", couCourseA.getId()); //课表ID
                delMap.put("targetObjId", couCourseA.getTargetObjId()); //班级ID
                delMap.put("minTime", couCourseA.getOpenStartTime()); //课表明细启用时间
                delMap.put("maxTime", couCourseA.getOpenStopTime()); //课表明细结束时间
                delMap.put("tenantId", baseApiEntity.getTenantId());
                delMap.put("sysOrgCode", baseApiEntity.getSysOrgCode());
                couTeachingJobExecuteMapperImpl.delTeachingJobExecute(delMap);
                CouCourseArrange updateCouCourseArrange = new CouCourseArrange();
                updateCouCourseArrange.setId(couCourseA.getId());
                updateCouCourseArrange.setCourseArrangeStatus(couTeachingJobExecuteVo.getArrangeStatus());
                if (!couCourseArrangeService.updateById(updateCouCourseArrange)) {
                    new IllegalArgumentException("修改课表状态失败！");
                    return Result.error("修改课表状态失败！");
                }

            }
            return Result.OK("教学任务下线成功！");
        }

        return Result.OK("教学任务日期处理成功！");
    }

    public Result<?> queryCouTeachingJobExecuteAll(Page<CouTeachingJobExecute> page, CouTeachingJobExecuteVo couTeachingJobExecuteVo) {

        /**
         * 由于目前测试阶段暂时写死，后期了解了整个架构流程后需要屏蔽这部分
         * mybatis 拦截器会对设置了租户表的操作，检测是否带有tenantId ,没有传入会默认设置为1。
         * 所以如果要分租户查询就使用 TenantContext.setTenant("128"); Tenant上下文对象，设置租户值。详细代码见
         * core 包的 MybatisPlusSaasConfig
         */
        //TenantContext.setTenant("128");
        /**
         * 方便测试固定班级id
         */
        List<JSONObject> whereInfo = new ArrayList();
        JSONObject returnInfo = new JSONObject();

        /**
         *  五、根据条件查询业务数据。
         */
        List<CouTeachingJobExecute> pageList = couTeachingJobExecuteMapperImpl.queryCouTeachingJobExecuteAll(couTeachingJobExecuteVo);
        page.setRecords(pageList);
        //设置字典数据
//        resfDictCode(pageList,sysBaseAPI);
        /**
         * 获取节次、开始时间、结束时间 ,这部分利用了arrayList内部排序机制是有序排序，
         * 也就是数据库查到什么就按什么顺序封装，因此，根据日期，星期，节次排好序。前段展示的数据节次时间和星期的课程内容是相对应的
         */
        List<JSONObject> sectionAndTimeList = couTeachingJobExecuteMapperImpl.getTeachingJobExeSection(couTeachingJobExecuteVo);
        //这个是为了查询周次，和周次开始结束时间根据业务加的。
        if (pageList != null && pageList.size() > 0) {
            whereInfo = couTeachingJobExecuteMapperImpl.queryCouTeachingJobExecuteWhere(couTeachingJobExecuteVo);
        }
        /**
         * 六、组装返回对象，可以返回多个，或者一个对象。这个根据业务需要进行组装。第七步到xml中查看
         */
        returnInfo.put("pageList", page);
        returnInfo.put("whereInfo", whereInfo);
        returnInfo.put("sectionAndTimeList", sectionAndTimeList);
        return Result.OK(returnInfo);
    }

    public Result<?> queryByIdDetail(Page<CouTeachingJobExecute> page, CouTeachingJobExecuteVo couTeachingJobExecuteVo) {


        JSONObject returnInfo = new JSONObject();

        /**
         *  五、根据条件查询业务数据。
         */
        List<CouTeachingJobExecute> pageList = couTeachingJobExecuteMapperImpl.queryCouTeachingJobExecuteAll(couTeachingJobExecuteVo);
        page.setRecords(pageList);

        /**
         * 六、组装返回对象，可以返回多个，或者一个对象。这个根据业务需要进行组装。第七步到xml中查看
         */
        returnInfo.put("pageList", page);
        return Result.OK(returnInfo);
    }

    public Result<?> queryTeacherJobDurationDate(Page<CouTeachingJobExecute> page, CouTeachingJobExecuteVo couTeachingJobExecuteVo) throws NoSuchFieldException, IllegalAccessException {

        JSONObject returnInfo = new JSONObject();
        /**
         *  五、根据条件查询业务数据。
         */
        List<CouTeachingJobExecute> pageList = couTeachingJobExecuteMapperImpl.queryTeacherJobDurationDate(page, couTeachingJobExecuteVo);
        List<DictModel> dictModelList = sysBaseAPI.getDictItems("teaching_job_exe_status");

        // clazzT 类型
        // groupFields 1.固定分组属性名称
        // groupFieldsAsName 2.固定分组属性显示别名
        // row2colsKeyFields  3.行转列动态列对应的关键属性字段，例如：科目字段（值是=语文 英语 数学）
        // newColsValueByFields 4.行转列动态列对应的值字段，允许空：例如：成绩字段（值是=98.5 99 59.5）
        // newColsnewColsValueUnitSymboles 5.动态列对应的单位符号，允许空，例如：“%” “人” “个”等
        // groupCalculationFun  6.聚聚合计算函数，支持[sum,count,max,min]不区分大小写
        // groupCalculationFunForValueField 7.聚合函数作用字段
        // groupCalculationAsColName 8.计算值列名字符串=列名+字符串，值=“Calculation”，所得列名=“语文Calculation”
        // newValueWeightCoefficientFieldes  //9.聚合函数使用的权重系数字段
        // newWeightCoefficientAsColName  //10.权重系数列名
        List<JSONObject> returObjList = new ArrayList<>();

        Class clazzT = CouTeachingJobExecute.class;
        String[] groupFields = new String[]{"gradeName", "teacherName"}; //1.固定分组属性名称
        String[] groupFieldsAsName = new String[]{"gradeName", "teacherName"};             //2.固定分组属性显示别名
        String[] row2colsKeyFields = new String[]{"teachingJobExeStatus"}; //状态名称 //3.行转列动态列对应的关键属性字段
        Map<String, String>[] row2colsKeyFieldsDict = new HashMap[]{new HashMap<String, String>()};
        for (DictModel d : dictModelList) {
            row2colsKeyFieldsDict[0].put(d.getValue(), d.getText());
        }

        String[] newColsValueByFields = new String[]{"teachingJobExeDuration"};  //各状态对应课时量，4.行转列动态列对应的值字段, 优良率数值取值字段
        String[] newColsValueUnitSymboles = new String[]{"时"};            //单位符号，5.动态列对应的单位符号，允许空，例如：“%” “人” “个”等
        String[] groupCalculationFun = new String[]{"sum"};                          //6.聚聚合计算函数，支持[sum,count,max,min]不区分大小写
        String[] groupCalculationFunForValueField = new String[]{"teachingJobExeDuration"};              //7.聚合函数作用字段
        String[][] groupCalculationAsColName = new String[][]{{"总课时量"}};                          //8.计算值列名字符串=列名+字符串，值=“Calculation”，所得列名=“语文Calculation”
        String newValueWeightCoefficientFieldes = null; /*9.聚合函数使用的权重系数字段,*/
        String newWeightCoefficientAsColName = null; //10.权重系数列名

        Row2ColModel row2ColModel = new Row2ColModel(clazzT, groupFields, groupFieldsAsName, row2colsKeyFields, row2colsKeyFieldsDict, newColsValueByFields, newColsValueUnitSymboles, groupCalculationFun, groupCalculationFunForValueField, groupCalculationAsColName, newValueWeightCoefficientFieldes, newWeightCoefficientAsColName);
        returObjList = row2ColTransfer.Row2ColToListJson(pageList, row2ColModel);

//        List<JSONObject> returObjList = setChangeCloumns(pageList, dictModelList); //此方法也可以完成字典码转列方式，但无法做到公用
        Page<JSONObject> returPage = new Page<>();
        BeanUtils.copyProperties(page, returPage);
        returPage.setRecords(returObjList);

        /**
         * 六、组装返回对象，可以返回多个，或者一个对象。这个根据业务需要进行组装。第七步到xml中查看
         */
        returnInfo.put("pageList", returPage);
        return Result.OK(returnInfo);
    }

    /**
     * 将字典码表的数据转换为动态列方式返回前段。字典码中的text为表头，value为对比的字典编码。
     * 其他业务使用时需要拷贝过去修改对比唯一值，根据业务需要进行修改
     *
     * @param pageList      业务表数据
     * @param dictModelList 字典码数据
     * @return
     */
    private List<JSONObject> setChangeCloumns(List<CouTeachingJobExecute> pageList, List<DictModel> dictModelList) {

        List<JSONObject> returObjList = new ArrayList<>();
        if (pageList == null || dictModelList == null) {
            return returObjList;
        }

        for (CouTeachingJobExecute couTeachingJobExecute : pageList) {
            boolean isFor = true;
            /**
             * 判断 返回数组中是否已经存在该循环对象，没有则跳到下面写入到动态列的对象中，进行下次循环
             */
            if (returObjList.size() > 0) {
                for (int returObjListIndex = 0; returObjListIndex < returObjList.size(); returObjListIndex++) {
                    /**
                     * 如果已经存在，循环匹配字典数据，
                     */
                    JSONObject jsonOld = returObjList.get(returObjListIndex);
                    if (couTeachingJobExecute.getTeacherId().equals(jsonOld.getString("teacherId"))) {
                        for (DictModel dictModel : dictModelList) {
                            //循环的对象的字典编码与已经存在的对象的状态编码一致则加相应的值。
                            if (couTeachingJobExecute.getTeachingJobExeStatus().equals(dictModel.getValue())) {
                                //否则不管 text为key, 课时字段为值
                                jsonOld.put(dictModel.getText(), jsonOld.getBigDecimal(dictModel.getText()).add(new BigDecimal(couTeachingJobExecute.getTeachingJobExeDuration())));
                            }
                        }
                        //如果已存在对象 需要增加相应的总课时量
                        BigDecimal teachingJobExeDurationOld = jsonOld.getBigDecimal("teachingJobExeDuration");
                        jsonOld.put("teachingJobExeDuration", teachingJobExeDurationOld.add(new BigDecimal(couTeachingJobExecute.getTeachingJobExeDuration())));
                        isFor = false;
                    }
                }
            }
            if (isFor) {
                //当对象第一次写入到，动态列对象里面时，
                JSONObject couTachingJob = (JSONObject) JSONObject.toJSON(couTeachingJobExecute);
                for (DictModel dictModel : dictModelList) {
                    //判断如果循环对象和字典码的编码值有相等的，则增加动态列表头，并把循环对象的值给它。 text为key, 课时字段为值
                    if (couTachingJob.getString("teachingJobExeStatus").equals(dictModel.getValue())) {
                        couTachingJob.put(dictModel.getText(), couTachingJob.getString("teachingJobExeDuration"));
                    } else {
                        //如果字典码在业务表中没有相应值。则给动态列赋默认值0
                        couTachingJob.put(dictModel.getText(), "0");
                    }
                }
                returObjList.add(couTachingJob);
            }
        }

        return returObjList;
    }

    public Result<?> queryTeacherJobDurationWeekSetIndex(Page<CouTeachingJobExecute> page, CouTeachingJobExecuteVo couTeachingJobExecuteVo) {

        JSONObject returnInfo = new JSONObject();
        /**
         *  五、根据条件查询业务数据。
         */
        List<CouTeachingJobExecute> pageList = couTeachingJobExecuteMapperImpl.queryTeacherJobDurationWeekSetIndex(page, couTeachingJobExecuteVo);
        page.setRecords(pageList);

        /**
         * 六、组装返回对象，可以返回多个，或者一个对象。这个根据业务需要进行组装。第七步到xml中查看
         */
        returnInfo.put("pageList", page);
        return Result.OK(returnInfo);
    }

    public Result<?> getTeacherAndSubjectCount(Page<JSONObject> page, CouTeachingJobExecuteVo couTeachingJobExecuteVo) {
        /**
         * 由于目前测试阶段暂时写死，后期了解了整个架构流程后需要屏蔽这部分
         * mybatis 拦截器会对设置了租户表的操作，检测是否带有tenantId ,没有传入会默认设置为1。
         * 所以如果要分租户查询就使用 TenantContext.setTenant("128"); Tenant上下文对象，设置租户值。详细代码见
         * core 包的 MybatisPlusSaasConfig
         */
        //TenantContext.setTenant("128");
        /**
         * 方便测试固定班级id
         */
        couTeachingJobExecuteVo.setClassId("1011497151580239732738");
        JSONObject returnInfo = new JSONObject();

        List<JSONObject> teacherCout = couTeachingJobExecuteMapperImpl.getTeacherCount(couTeachingJobExecuteVo);
        List<JSONObject> subjectCout = couTeachingJobExecuteMapperImpl.getSubjectCount(couTeachingJobExecuteVo);
        returnInfo.put("teacherCout", teacherCout);
        returnInfo.put("subjectCout", subjectCout);

        return Result.OK(returnInfo);
    }

    public Result<?> changeCouresTeacher(JSONObject jsonInfo) {
        /**
         * 由于目前测试阶段暂时写死，后期了解了整个架构流程后需要屏蔽这部分
         * mybatis 拦截器会对设置了租户表的操作，检测是否带有tenantId ,没有传入会默认设置为1。
         * 所以如果要分租户查询就使用 TenantContext.setTenant("128"); Tenant上下文对象，设置租户值。详细代码见
         * core 包的 MybatisPlusSaasConfig
         */
        //TenantContext.setTenant("128");
        /**
         * 方便测试固定班级id
         */
        JSONObject returnInfo = new JSONObject();
        CouTeachingJobExecute oldCouTeachingJobExecute = null;
        String newTeacherId = null;
        if (jsonInfo.containsKey("oldCouTeachingJobExecute")) {
            oldCouTeachingJobExecute = JSONObject.parseObject(jsonInfo.getJSONObject("oldCouTeachingJobExecute").toJSONString(), CouTeachingJobExecute.class);
        }
        if (jsonInfo.containsKey("newTeacherId")) {
            newTeacherId = jsonInfo.getString("newTeacherId");
        }

        //某节课进行交换进行处理
        if (oldCouTeachingJobExecute != null && newTeacherId != null && !"".equals(newTeacherId)) {
            return updateCourseTeacher(oldCouTeachingJobExecute, newTeacherId);
        } else {
            new IllegalArgumentException("未传递代课老师，被代课老师！");
            return Result.error("未传递代课老师，被代课老师！");
        }
    }

    public Result<?> changeCoures(JSONObject jsonInfo) {
        /**
         * 由于目前测试阶段暂时写死，后期了解了整个架构流程后需要屏蔽这部分
         * mybatis 拦截器会对设置了租户表的操作，检测是否带有tenantId ,没有传入会默认设置为1。
         * 所以如果要分租户查询就使用 TenantContext.setTenant("128"); Tenant上下文对象，设置租户值。详细代码见
         * core 包的 MybatisPlusSaasConfig
         */
        //TenantContext.setTenant("128");
        /**
         * 方便测试固定班级id
         */
        JSONObject returnInfo = new JSONObject();
        CouTeachingJobExecute tooData = null;
        CouTeachingJobExecute oneData = null;
        CouTeachingJobExecute oneWeekData = null;
        CouTeachingJobExecute tooWeekData = null;
        if (jsonInfo.containsKey("oneData")) {
            oneData = JSONObject.parseObject(jsonInfo.getJSONObject("oneData").toJSONString(), CouTeachingJobExecute.class);
        }
        if (jsonInfo.containsKey("tooData")) {
            tooData = JSONObject.parseObject(jsonInfo.getJSONObject("tooData").toJSONString(), CouTeachingJobExecute.class);
        }
        if (jsonInfo.containsKey("oneWeekData")) {
            oneWeekData = JSONObject.parseObject(jsonInfo.getJSONObject("oneWeekData").toJSONString(), CouTeachingJobExecute.class);
        }
        if (jsonInfo.containsKey("tooWeekData")) {
            tooWeekData = JSONObject.parseObject(jsonInfo.getJSONObject("tooWeekData").toJSONString(), CouTeachingJobExecute.class);
        }
        //某节课进行交换进行处理
        if (oneData != null && tooData != null) {
            return checkCourseData(oneData, tooData);
        } else if (oneWeekData != null && tooWeekData != null) {
            return checkCourseWeekData(oneWeekData, tooWeekData);
        } else {
            new IllegalArgumentException("未传递交换对象，请选择交换对象！");
            return Result.error("未传递交换对象，请选择交换对象！");
        }
    }

    private Result<?> checkCourseData(CouTeachingJobExecute oneData, CouTeachingJobExecute tooData) {

        if (oneData == null || tooData == null) {
            return Result.error("未传递交换对象，请选择交换对象！");
        }
        //校验数据及让原有数据失效
        CouTeachingJobExecute oneCouTeachingJobExecute = this.getById(oneData.getId());
        if (oneCouTeachingJobExecute == null) {
            new IllegalArgumentException("未找到对应oneData数据");
            return Result.error("未找到对应oneData数据！");
        }
        CouTeachingJobExecute updateCouTachingJobExecute = new CouTeachingJobExecute();
        updateCouTachingJobExecute.setIzOpen(0);
        updateCouTachingJobExecute.setId(oneCouTeachingJobExecute.getId());
        if (!this.updateById(updateCouTachingJobExecute)) {
            new IllegalArgumentException("修改oneData数据状态失败");
            return Result.error("修改oneData数据状态失败！");
        }

        CouTeachingJobExecute tooCouTeachingJobExecute = this.getById(tooData.getId());
        if (tooCouTeachingJobExecute == null) {
            new IllegalArgumentException("未找到对应tooData数据");
            return Result.error("未找到对应tooData数据！");
        }
        updateCouTachingJobExecute.setIzOpen(0);
        updateCouTachingJobExecute.setId(tooCouTeachingJobExecute.getId());
        if (!this.updateById(updateCouTachingJobExecute)) {
            new IllegalArgumentException("修改tooData数据状态失败");
            return Result.error("修改tooData数据状态失败！");
        }

        //新加一条数据
        Date oneTeachingJobExeDate = oneCouTeachingJobExecute.getTeachingJobExeDate();
        Integer oneTeachingJobExeWeek = oneCouTeachingJobExecute.getTeachingJobExeWeek();
        Integer oneTeachingJobExeSection = oneCouTeachingJobExecute.getTeachingJobExeSection();
        Integer oneWeekSetIndex = oneCouTeachingJobExecute.getWeekSetIndex();
        String oneTeaJobExeSectionName = oneCouTeachingJobExecute.getTeaJobExeSectionName();
        String oneTeacherId = oneCouTeachingJobExecute.getTeacherId();
        String oneSubjectId = oneCouTeachingJobExecute.getSubjectId();

        Date tooTeachingJobExeDate = tooCouTeachingJobExecute.getTeachingJobExeDate();
        Integer tooTeachingJobExeWeek = tooCouTeachingJobExecute.getTeachingJobExeWeek();
        Integer tooTeachingJobExeSection = tooCouTeachingJobExecute.getTeachingJobExeSection();
        Integer tooWeekSetIndex = tooCouTeachingJobExecute.getWeekSetIndex();
        String tooTeaJobExeSectionName = tooCouTeachingJobExecute.getTeaJobExeSectionName();
        String tooTeacherId = tooCouTeachingJobExecute.getTeacherId();
        String tooSubjectId = tooCouTeachingJobExecute.getSubjectId();

        /**
         * 换课 逻辑： 页面展示是以实际星期为主，要换课，其实就是将对方的实际星期（tooTeachingJobExeWeek）替换为自己的实际星期，
         * 星期换了后，还有一个问题就是第几周也要跟着换(tooWeekSetIndex)，这样页面展示位置就已经调换了，然后吧实际日期互换这样整个课就调换过来了。
         * 其他都不变这样就完成了换课
         */
        oneCouTeachingJobExecute.setTeachingJobExeDate(tooTeachingJobExeDate); //换日期
        oneCouTeachingJobExecute.setTeachingJobExeWeek(tooTeachingJobExeWeek); //换实际星期
        oneCouTeachingJobExecute.setTeachingJobExeNewWeek(oneTeachingJobExeWeek);//将原来的执行星期改为实际星期
        oneCouTeachingJobExecute.setWeekSetIndex(tooWeekSetIndex);//换第几周
        oneCouTeachingJobExecute.setTeachingJobExeSection(tooTeachingJobExeSection);//换节次
        oneCouTeachingJobExecute.setTeaJobExeSectionName(tooTeaJobExeSectionName);//换节次名称
        oneCouTeachingJobExecute.setQuoteTeachingJobId(oneData.getQuoteTeachingJobId() == null ? oneData.getId() : oneData.getQuoteTeachingJobId());
        oneCouTeachingJobExecute.setId(null);
        if (!this.save(oneCouTeachingJobExecute)) {
            new IllegalArgumentException("新增oneData数据失败");
            return Result.error("新增oneData数据失败！");
        }

        tooCouTeachingJobExecute.setTeachingJobExeDate(oneTeachingJobExeDate);
        tooCouTeachingJobExecute.setTeachingJobExeWeek(oneTeachingJobExeWeek);
        tooCouTeachingJobExecute.setTeachingJobExeNewWeek(tooTeachingJobExeWeek);
        tooCouTeachingJobExecute.setWeekSetIndex(oneWeekSetIndex);//换第几周
        tooCouTeachingJobExecute.setTeachingJobExeSection(oneTeachingJobExeSection);//换节次
        tooCouTeachingJobExecute.setTeaJobExeSectionName(oneTeaJobExeSectionName);//换节次名称
        tooCouTeachingJobExecute.setQuoteTeachingJobId(tooData.getQuoteTeachingJobId() == null ? tooData.getId() : tooData.getQuoteTeachingJobId());
        tooCouTeachingJobExecute.setId(null);
        if (!this.save(tooCouTeachingJobExecute)) {
            new IllegalArgumentException("新增tooData数据失败");
            return Result.error("新增tooData数据失败！");
        }

        return Result.OK("处理换课完成！");


    }

    private Result<?> checkCourseWeekData(CouTeachingJobExecute oneWeekData, CouTeachingJobExecute tooWeekData) {

        if (oneWeekData == null || tooWeekData == null) {
            return Result.error("未传递交换对象，请选择交换对象！");
        }
        List<CouGrade> couGradeList = null;
        List<CouClass> couClassList = null;
        //如果是选择的是全校，先查学校所属的所有年级，再查年级所有的班级，班级所有的启用的课表，进行交换
        if (oneWeekData.getSchoolId() != null && !"".equals(oneWeekData.getSchoolId()) && "-1".equals(oneWeekData.getSchoolId())) {

            QueryWrapper<CouGrade> couGradeQueryWrapper = new QueryWrapper();
            couGradeQueryWrapper.eq("tenant_id", TenantContext.getTenant());
            couGradeList = couGradeService.list(couGradeQueryWrapper);
            if (couGradeList == null || couGradeList.size() < 1) {
                new IllegalArgumentException("未找到学校对应年级信息，请联系管理员！");
                return Result.error("未找到学校对应年级信息，请联系管理员！");
            }
            //如果是选择的是年级，查年级所有的班级，班级所有的启用的课表，进行交换
        } else if (oneWeekData.getGradeId() != null && !"".equals(oneWeekData.getGradeId())) {
            QueryWrapper<CouGrade> couGradeQueryWrapper = new QueryWrapper();
            couGradeQueryWrapper.eq("tenant_id", TenantContext.getTenant());
            couGradeQueryWrapper.eq("id", oneWeekData.getGradeId());
            couGradeList = couGradeService.list(couGradeQueryWrapper);
            if (couGradeList == null || couGradeList.size() < 1) {
                new IllegalArgumentException("未找到学校对应年级信息，请联系管理员！");
                return Result.error("未找到学校对应年级信息，请联系管理员！");
            }
        } else if (oneWeekData.getClassId() != null && !"".equals(oneWeekData.getClassId())) {
            QueryWrapper<CouClass> couClassQueryWrapper = new QueryWrapper();
            couClassQueryWrapper.eq("tenant_id", TenantContext.getTenant());
            couClassQueryWrapper.eq("id", oneWeekData.getClassId());
            couClassQueryWrapper.eq("class_iz_open", 1);
            couClassQueryWrapper.eq("class_status", 1);
            couClassList = couClassService.list(couClassQueryWrapper);
            if (couClassList == null || couClassList.size() < 1) {
                new IllegalArgumentException("未找到学校对应班级信息，请联系管理员！");
                return Result.error("未找到学校对应班级信息，请联系管理员！");
            }
        }
        return runCheckCourseData(oneWeekData, tooWeekData, couGradeList, couClassList);
    }

    private Result<?> runCheckCourseData(CouTeachingJobExecute oneWeekData, CouTeachingJobExecute tooWeekData, List<CouGrade> couGradeList, List<CouClass> couClassList) {
        //选择全校或者整个年级处理数据
        if (couGradeList != null && couGradeList.size() > 0) {
            for (CouGrade grade : couGradeList) {
                QueryWrapper<CouClass> couClassQueryWrapper = new QueryWrapper();
                couClassQueryWrapper.eq("tenant_id", grade.getTenantId());
                couClassQueryWrapper.eq("grade_code", grade.getId());
                couClassQueryWrapper.eq("class_iz_open", 1);
                couClassQueryWrapper.eq("class_status", 1);
                List<CouClass> couClassListNew = couClassService.list(couClassQueryWrapper);
                if (couClassListNew != null && couClassListNew.size() > 0) {
                    for (CouClass couClass : couClassListNew) {
                        QueryWrapper<CouCourseArrange> couCourseArrangeQueryWrapper = new QueryWrapper<>();
                        couCourseArrangeQueryWrapper.eq("tenant_id", grade.getTenantId());
                        couCourseArrangeQueryWrapper.eq("target_obj_id", couClass.getId());
                        couCourseArrangeQueryWrapper.eq("iz_open", 1);
                        couCourseArrangeQueryWrapper.eq("iz_delete", 0);
                        List<CouCourseArrange> couCourseArrangeList = couCourseArrangeService.list(couCourseArrangeQueryWrapper);
                        if (couCourseArrangeList != null && couCourseArrangeList.size() > 0) {
                            for (CouCourseArrange couCourseArrange : couCourseArrangeList) {
                                oneWeekData.setClassId(couClass.getId());
                                oneWeekData.setCourseArrangeId(couCourseArrange.getId());
                                tooWeekData.setClassId(couClass.getId());
                                tooWeekData.setCourseArrangeId(couCourseArrange.getId());
                                exectWeekData(oneWeekData, tooWeekData);
                            }

                        }
                    }

                }
            }
            //选择了某一个班级处理
        } else if (couClassList != null && couClassList.size() > 0) {
            for (CouClass couClass : couClassList) {
                QueryWrapper<CouCourseArrange> couCourseArrangeQueryWrapper = new QueryWrapper<>();
                couCourseArrangeQueryWrapper.eq("tenant_id", couClass.getTenantId());
                couCourseArrangeQueryWrapper.eq("target_obj_id", couClass.getId());
                couCourseArrangeQueryWrapper.eq("iz_open", 1);
                couCourseArrangeQueryWrapper.eq("iz_delete", 0);
                List<CouCourseArrange> couCourseArrangeList = couCourseArrangeService.list(couCourseArrangeQueryWrapper);
                if (couCourseArrangeList != null && couCourseArrangeList.size() > 0) {
                    for (CouCourseArrange couCourseArrange : couCourseArrangeList) {
                        oneWeekData.setClassId(couClass.getId());
                        oneWeekData.setCourseArrangeId(couCourseArrange.getId());
                        tooWeekData.setClassId(couClass.getId());
                        tooWeekData.setCourseArrangeId(couCourseArrange.getId());
                        exectWeekData(oneWeekData, tooWeekData);
                    }

                }
            }
        }


        return Result.OK("处理换课完成！");
    }

    @Nullable
    private void exectWeekData(CouTeachingJobExecute oneWeekData, CouTeachingJobExecute tooWeekData) {
        QueryWrapper<CouTeachingJobExecute> queryOneWrapper = new QueryWrapper();
        queryOneWrapper.eq("teaching_job_exe_date", oneWeekData.getTeachingJobExeDate());
        queryOneWrapper.eq("course_arrange_id", oneWeekData.getCourseArrangeId());
        queryOneWrapper.eq("class_id", oneWeekData.getClassId());
        queryOneWrapper.eq("iz_open", 1);
        queryOneWrapper.eq("del_flag", 0);
        queryOneWrapper.eq("tenant_id", TenantContext.getTenant());
        List<CouTeachingJobExecute> oneWeekCouTeachingJobExecuteList = this.list(queryOneWrapper);
        if (oneWeekCouTeachingJobExecuteList == null || oneWeekCouTeachingJobExecuteList.size() < 1) {
            new IllegalArgumentException("未找到对应oneWeekData数据");
        }
        QueryWrapper<CouTeachingJobExecute> queryTooWrapper = new QueryWrapper();
        queryTooWrapper.eq("teaching_job_exe_date", tooWeekData.getTeachingJobExeDate());
        queryOneWrapper.eq("course_arrange_id", tooWeekData.getCourseArrangeId());
        queryTooWrapper.eq("class_id", tooWeekData.getClassId());
        queryTooWrapper.eq("iz_open", 1);
        queryTooWrapper.eq("del_flag", 0);
        queryTooWrapper.eq("tenant_id", TenantContext.getTenant());
        List<CouTeachingJobExecute> tooWeekCouTeachingJobExecuteList = this.list(queryTooWrapper);
        if (tooWeekCouTeachingJobExecuteList == null || tooWeekCouTeachingJobExecuteList.size() < 1) {
            new IllegalArgumentException("未找到对应tooWeekData数据");
        }
        for (CouTeachingJobExecute oneData : oneWeekCouTeachingJobExecuteList) {
            for (CouTeachingJobExecute tooData : tooWeekCouTeachingJobExecuteList) {
                if (oneData.getTeachingJobExeSection() == tooData.getTeachingJobExeSection()) {
                    checkCourseData(oneData, tooData);
                    break;
                }
            }
        }
    }


    private Result<?> updateCourseTeacher(CouTeachingJobExecute oldCouTeachingJobExecute, String newTeacherId) {

        if (oldCouTeachingJobExecute == null || newTeacherId == null) {
            return Result.error("未传递代课老师，被代课老师！");
        }
        //校验数据及让原有数据失效
        CouTeachingJobExecute oldCouTeachingJobExecuteNew = this.getById(oldCouTeachingJobExecute.getId());
        if (oldCouTeachingJobExecuteNew == null) {
            new IllegalArgumentException("未找到对应oldCouTeachingJobExecute数据");
            return Result.error("未找到对应oldCouTeachingJobExecute数据！");
        }
        CouTeachingJobExecute updateCouTachingJobExecute = new CouTeachingJobExecute();
        updateCouTachingJobExecute.setTeachingJobExeStatus(CouTeachingJobExecute.TEACHING_JOB_EXE_STATUS_OUT);
        updateCouTachingJobExecute.setIzOpen(0);
        updateCouTachingJobExecute.setId(oldCouTeachingJobExecuteNew.getId());
        if (!this.updateById(updateCouTachingJobExecute)) {
            new IllegalArgumentException("修改oldCouTeachingJobExecute数据状态失败");
            return Result.error("修改oldCouTeachingJobExecute数据状态失败！");
        }

        oldCouTeachingJobExecuteNew.setTeachingJobExeStatus(CouTeachingJobExecute.TEACHING_JOB_EXE_STATUS_IN);
        oldCouTeachingJobExecuteNew.setTeacherId(newTeacherId);
        oldCouTeachingJobExecuteNew.setQuoteTeachingJobId(oldCouTeachingJobExecute.getQuoteTeachingJobId() == null ? oldCouTeachingJobExecute.getId() : oldCouTeachingJobExecute.getQuoteTeachingJobId());
        oldCouTeachingJobExecuteNew.setId(null);
        if (!this.save(oldCouTeachingJobExecuteNew)) {
            new IllegalArgumentException("新增oldCouTeachingJobExecuteNew数据失败");
            return Result.error("新增oldCouTeachingJobExecuteNew数据失败！");
        }

        return Result.OK("处理临时代课完成！");


    }

    private void resfDictCode(List<CouTeachingJobExecute> pageList, ISysBaseAPI sysBaseAPI) {
        if (pageList == null || pageList.size() < 1) {
            return;
        }
        List<DictModel> dictModelList = sysBaseAPI.getDictItems("cour_sch_tem_auto_flag");
        if (dictModelList == null || dictModelList.size() < 1) {
            new IllegalArgumentException("未查询到字典数据，请检查字典数据！");
            return;
        }
        for (CouTeachingJobExecute couTeachingJobExecute : pageList) {
            //教室
            if (couTeachingJobExecute.getTeacherId().length() <= 3) {
                for (DictModel dictModel : dictModelList) {
                    if (dictModel.getValue().equals(couTeachingJobExecute.getTeacherId())) {
                        couTeachingJobExecute.setTeacherName(dictModel.getText());
                    }
                }
            }
            //班级
            if (couTeachingJobExecute.getClassroomId().length() <= 3) {
                for (DictModel dictModel : dictModelList) {
                    if (dictModel.getValue().equals(couTeachingJobExecute.getClassroomId())) {
                        couTeachingJobExecute.setClassName(dictModel.getText());
                    }
                }
            }
            //科目
            if (couTeachingJobExecute.getSubjectId().length() <= 3) {
                for (DictModel dictModel : dictModelList) {
                    if (dictModel.getValue().equals(couTeachingJobExecute.getSubjectId())) {
                        couTeachingJobExecute.setSubjectName(dictModel.getText());
                    }
                }
            }
        }
    }
}
